package com.abel.bigwater.kmgw

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.dataserver.model.PacketNotEnoughException
import com.abel.bigwater.dataserver.model.ewide.KmingPacket
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageDecoder
import org.slf4j.LoggerFactory

class EwideDecoder : ByteToMessageDecoder() {
    /**
     * Decode the from one [ByteBuf] to an other. This method will be called till either the input
     * [ByteBuf] has nothing to read when return from this method or till nothing was read from the input
     * [ByteBuf].
     *
     * @param ctx           the [ChannelHandlerContext] which this [ByteToMessageDecoder] belongs to
     * @param in            the [ByteBuf] from which to read data
     * @param out           the [List] to which decoded messages should be added
     * @throws Exception    is thrown if an error occurs
     */
    override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
        if (`in` == null) {
            lgr.error("byte-buf can't be null for parsing")
            return
        }

        val msg = BcdString.hexString(`in`, withBlank = true)
        lgr.info("got bytes from ${ctx?.channel()?.remoteAddress()}:\r\n$msg")

        do {
            val p = KmingPacket().apply {
                streamType = "TCP"
                device = "EW_TCP:${ctx?.channel()?.remoteAddress()}".take(32)
                server = "EW_TCP:${ctx?.channel()?.localAddress()}".take(32)
            }

            try {
                if (p.parseBuf(`in`)) {
                    out?.add(p)
                } else break
            } catch (ex: PacketNotEnoughException) {
                lgr.warn("wait for more bytes: ${ex.message}")
                // just wait.
            }
        } while (true)
    }

    companion object {
        private val lgr = LoggerFactory.getLogger(EwideDecoder::class.java)
    }
}
